package com.yycx.module.file.provider.controller;


import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.google.common.collect.Lists;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.SettingConstant;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.JsonUtils;
import com.yycx.common.utils.RedisUtils;
import com.yycx.common.utils.SpringContextHolder;
import com.yycx.module.file.client.entity.SysFile;
import com.yycx.module.file.provider.enums.StoreTypeEnum;
import com.yycx.module.file.provider.handler.FileRemoveHandler;
import com.yycx.module.file.provider.oss.FileUploadUtil;
import com.yycx.module.file.provider.oss.client.AliOssClient;
import com.yycx.module.file.provider.service.SysFileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * OSS文件上传控制器
 *
 * @author flyme
 * @date 2019-06-03
 */
@Slf4j
@Api(tags = "文件模块-文件管理")
@RestController
public class SysFileController {

    @Autowired
    private SysFileService fileService;
    @Autowired
    public RedisUtils redisUtils;
    @Autowired
    private AliOssClient aliOssUtil;

    @ApiOperation(value = "多文件上传")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "文件流对象,接收数组格式", required = true, dataType = "MultipartFile", paramType = "form", allowMultiple = true)
            , @ApiImplicitParam(name = "busType", value = "业务类型", paramType = "form")
            , @ApiImplicitParam(name = "busId", value = "业务Id", paramType = "form")
            , @ApiImplicitParam(name = "fileType", value = "文件类型", required = true, defaultValue = "image", paramType = "form")}
    )
    @RequestMapping(value = "/file/batch/upload", method = RequestMethod.POST)
    @CrossOrigin
    public ResultBody batchUpload(HttpServletRequest request,
                                  @RequestParam(value = "file") MultipartFile[] files
            , @RequestParam(value = "busId", required = false) Long busId
            , @RequestParam(value = "handlerName", required = false) String handlerName
            , @RequestParam(value = "busType", required = false) String busType) {
        EntityMap map = fileService.upload(request, files, busId, busType, handlerName);
        return ResultBody.ok(map);
    }


    /**
     * 上传文件
     *
     * @param request
     * @param file
     * @param fileType  文件类型
     * @param fileName  文件固定名称
     * @param busId     业务ID
     * @param busType   业务类型
     * @param sync      是否异步上传 默认异步
     * @param handlerName
     * @param base64Img
     * @return
     */
    @RequestMapping(value = "/file/upload", method = RequestMethod.POST)
    public ResultBody fileUpload(HttpServletRequest request,
                                 @RequestParam(value = "file") MultipartFile file
            , @RequestParam(value = "fileType", defaultValue = "image") String fileType
            , @RequestParam(value = "busId", required = false) Long busId
            , @RequestParam(value = "busType", required = false) String busType
            , @RequestParam(value = "fileTag", required = false) Integer fileTag
            , @RequestParam(value = "sync", required = false, defaultValue = "0") String sync
            , @RequestParam(value = "fileName", required = false) String fileName
            , @RequestParam(value = "handlerName", required = false) String handlerName
            , @RequestParam(value = "base64Img", required = false) String base64Img
    ) {
        EntityMap map = fileService.upload(request, file, busId, busType,fileTag, handlerName);
        return ResultBody.ok(map);
    }

    @GetMapping(value = "/common/file/view/{id}", produces = "application/octet-stream")
    @ApiOperation(value = "文件下载", position = 3)
    @CrossOrigin
    @ApiImplicitParam(value = "文件ID", name = "id", paramType = "form")
    public void view(@PathVariable String id, HttpServletResponse response) throws IOException {
        SysFile file = fileService.getById(id);
        if (FlymeUtils.isNotEmpty(file)) {
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(file.getFileKey(), "UTF-8"));
            response.addHeader("Content-Length", file.getFileSize().toString());
            response.setContentType("application/octet-stream;charset=UTF-8");
            if (ObjectUtils.isNotEmpty(file.getLocalPath())) {
                FileUploadUtil.view(file.getLocalPath(), response);
            }
        }

    }

    /**
     * 图片预览
     */
    @RequestMapping(value = {"/common/file/view/image/{id}/{type}", "/common/file/view/image/{id}"}, method = RequestMethod.GET)
    public void getUserLogo(@PathVariable String id, @PathVariable(required = false) String type, HttpServletResponse response) {
        SysFile file = fileService.getById(id);
        // 设置返回内容格式
        response.setContentType(file.getFileType());
        String filePath;
        //预览大图
        if (FlymeUtils.isNotEmpty(type) && type.equals("original")) {
            filePath = file.getLocalPath();
        } else {
            filePath = FlymeUtils.getString(file.getSmallPath(), file.getLocalPath());
        }
        // 括号里参数为文件图片路径
        File f = new File(filePath);
        // 如果文件存在
        if (f.exists()) {
            InputStream in;
            try {
                in = new FileInputStream(f);
                // 创建输出流
                OutputStream os = response.getOutputStream();
                byte[] b = new byte[1024];
                while (in.read(b) != -1) {
                    os.write(b);
                }
                in.close();
                os.flush();
                os.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @PostMapping(value = "/file/remove")
    @ApiOperation(value = "文件删除")
    public ResultBody remove(@RequestParam Long[] fileIds, String handlerName) {
        List<EntityMap> fileList = Lists.newArrayList();
        String used = redisUtils.getConfig(SettingConstant.OSS_USED);
        List<String> objectIds = new ArrayList<>();
        for (Long id : fileIds) {
            SysFile file = fileService.getById(id);
            objectIds.add(file.getFileKey());
            FileUploadUtil.deleteFileByPath(file.getLocalPath());
            if (FlymeUtils.isNotEmpty(file.getSmallPath())) {
                FileUploadUtil.deleteFileByPath(file.getSmallPath());
            }
            fileService.removeById(id);
            Map<String, Object> map = JsonUtils.beanToMap(file);
            EntityMap entityMap = new EntityMap();
            entityMap.putAll(map);
            fileList.add(entityMap);
        }
        if (used.equals(StoreTypeEnum.ALI_OSS.name())) {
            //刪除阿里OSS文件
            if (FlymeUtils.isNotEmpty(objectIds)) {
                aliOssUtil.deleteFile(objectIds);
            }
        }
        if (FlymeUtils.isNotEmpty(handlerName)) {
            FileRemoveHandler fileRemoveHandler = SpringContextHolder.getHandler(handlerName, FileRemoveHandler.class);
            if (ObjectUtils.isNotEmpty(fileRemoveHandler)) {
                //执行文件删除扩展
                fileRemoveHandler.complete(fileList);
            }
        }
        return ResultBody.msg("删除成功");
    }

    @ApiOperation(value = "根据业务类型查询文件列表", notes = "根据业务类型查询文件列表")
    @GetMapping(value = "/file/list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "busType", required = true, value = "主键", paramType = "form"),
            @ApiImplicitParam(name = "busId", required = true, value = "业务ID", paramType = "form"),
            @ApiImplicitParam(name = "fileType", value = "文件类型", paramType = "form")
    })
    public ResultBody list(@RequestParam(value = "busId") Long busId, @RequestParam(value = "busType") String busType, @RequestParam(value = "fileType") String fileType) {
        List<EntityMap> fileList = fileService.selectFileListByFileType(busId, busType, fileType);
        return ResultBody.ok(fileList);
    }

    /**
     * 重置上传进度
     **/
    @RequestMapping("resetPercent")
    @ResponseBody
    public String resetPercent(HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute("upload_percent", 0);
        return "重置进度";
    }


    @ApiOperation(value = "单文件上传(支持跨域)")
    @ApiImplicitParams({@ApiImplicitParam(name = "file", value = "文件流对象,接收数组格式", required = true, paramType = "form", dataType = "__File"),
            @ApiImplicitParam(name = "fileType", value = "文件类型", required = true, defaultValue = "image", paramType = "form"),
            @ApiImplicitParam(name = "busType", value = "业务类型", paramType = "form"),
            @ApiImplicitParam(name = "busId", value = "业务Id", paramType = "form")
    }
    )
    @RequestMapping(value = "/file/uploadByCross", method = RequestMethod.POST)
    @CrossOrigin
    public Map<String, Object> signUpload(HttpServletRequest request, @RequestParam(value = "file") MultipartFile file, @RequestParam(value = "fileType", defaultValue = "image") String fileType
            , @RequestParam(value = "busId", required = false) Long busId
            , @RequestParam(value = "busType", required = false) String busType
            , @RequestParam(value = "busType", required = false) Integer fileGroup
            , @RequestParam(value = "handlerName", required = false) String handlerName
            , @RequestParam(value = "base64Img", required = false) String base64Img
    ) {
        EntityMap map = fileService.upload(request, file, busId, busType,fileGroup, handlerName);
        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        result.put("data", map);
        return result;
    }

}
